<template>
  <div class="play_page" :class="[show ? 'show' : 'hidden']">
    <header class="header u-f">
      <div class="icon_box u-f u-f-ac u-f-jc" @click.stop="close">
        <i class="iconfont icon-arrowdown"></i>
      </div>
      <div class="content u-f u-f-jc u-f-column u-f1">
        <p class="name van-ellipsis">{{ songs.name }}</p>
        <p class="author">
          <span v-for="(item, i) in songs.ar" :key="item.id">
            <span v-if="i === 0">{{ item.name }}</span>
            <span v-else>/{{ item.name }}</span>
          </span>
        </p>
      </div>
      <div class="icon_box u-f u-f-ac u-f-jc">
        <i class="iconfont icon-fenxiang2"></i>
      </div>
    </header>

    <div
      class="main"
      ref="mainRef"
      @touchstart="touchStartMain"
      @touchend="touchEndMain"
    >
      <ul class="line_list" ref="lineListRef">
        <li
          class="list"
          :class="[currentLyricLineId === item.id ? 'active' : '']"
          v-for="item in lineArr"
          :key="item.id"
        >
          <span
            class="text"
            :style="{
              'animation-duration':
                currentLyricLineId === item.id ? lineTextAnimation : '0',
              'animation-play-state':
                playOrPause === 'play' ? 'running' : 'paused',
            }"
            >{{ item.text }}</span
          >
        </li>
      </ul>
    </div>

    <div class="footer">
      <sky-audio
        ref="skyAuio"
        :time="songs.dt"
        @changeLyricTime="getLyricTime"
      ></sky-audio>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, Ref, ref, watch } from 'vue'
import SkyAudio from '@/components/common/sky-audio.vue'
import { songDetail, lyric } from '@/api/play'
import { Store, useStore } from 'vuex'

// 控制组件显示
const handleVisible = (store: Store<any>) => {
  const show: Ref<boolean> = ref(false)

  const open = () => {
    show.value = true
  }

  const close = () => {
    show.value = false
  }

  watch(
    () => store.state.currentPlaying,
    (newVal) => {
      if (!newVal.id) {
        store.commit('setPlayOrPause', '')
        close()
      }
    },
    {
      immediate: true,
    }
  )

  return {
    show,
    open,
    close,
  }
}

// 处理音频
const handleAudio = () => {
  const skyAuio: Ref<any> = ref(null)

  const playAudio = () => {
    skyAuio.value?.playAudio()
  }

  const pauseAudio = () => {
    skyAuio.value?.pauseAudio()
  }

  return {
    skyAuio,
    playAudio,
    pauseAudio,
  }
}

// 获取歌曲详情
const handleSongDetail = (store: Store<any>) => {
  const songs: Ref<any> = ref({
    name: '',
    dt: 0,
    ar: [],
  })

  const removeZero = (num: number): number => {
    let str = num.toString()
    str = str.replace(/0*$/g, '')
    const dt = str.slice(0, 3)
    return Number(dt)
  }

  const getSongDetail = async () => {
    const { data } = await songDetail(store.state.currentPlaying?.id)

    let obj = data.songs[0]
    if ('dt' in obj) {
      obj.dt = removeZero(obj.dt)
    }

    songs.value = obj
  }

  watch(
    () => store.state.currentPlaying,
    (newVal) => {
      if (newVal.id) {
        getSongDetail()
      }
    },
    {
      immediate: true,
    }
  )

  return {
    songs,
    getSongDetail,
  }
}

// 获取歌词
interface LyricObject {
  id: number
  time: number
  text: string
}
// {
//   id: 4
//   text: " 制作人 : 袁娅维/The Monarch"
//   time: 3
// }

const handleSongLyric = (
  store: Store<any>,
  stopScroll: Ref<boolean>,
  mainRef: Ref<any>,
  lineListRef: Ref<any>
) => {
  // 处理好后的歌词
  const lineArr: Ref<Array<LyricObject>> = ref([])
  // 当前播放的歌词id
  const currentLyricLineId: Ref<number> = ref(0)
  // 所有歌词 dom 节点
  let linEl: any = null
  // 当前播放的那一行歌词所需要的时间
  const lineTextAnimation: Ref<string> = ref('1s')

  const formatLyricTime = (time: string): string => {
    let allTime = 0

    const tArr = time.replace('[', '').replace(']', '').split(':')

    allTime = Number(tArr[0]) * 60 + Number(tArr[1])

    return allTime.toFixed(1)
  }

  const getSongLyric = async () => {
    const { data } = await lyric(store.state.currentPlaying?.id)
    const lyricStr = data.lrc.lyric
    const newLineArr: Array<LyricObject> = []

    const oldLineArr = lyricStr.split('\n').filter((item: string) => {
      if (item) {
        return item
      }
    })

    if (!lyricStr || oldLineArr.length === 0) {
      // 没有歌词
      lineArr.value = []
      return false
    }

    oldLineArr.forEach((item: string, index: number) => {
      const matchArr: RegExpMatchArray | null = item.match(/\[.*\]/)
      const time = matchArr ? formatLyricTime(matchArr[0]) : 0
      const input = matchArr ? matchArr['input'] : ''
      const text = matchArr ? (input as string).replace(matchArr[0], '') : ''

      newLineArr.push({
        id: index + 1,
        time: Number(time),
        text,
      })
    })
    console.log(newLineArr)

    lineArr.value = newLineArr
  }

  const getLyricTime = (time: number) => {
    if (!linEl) {
      linEl = lineListRef.value.children
    }
    for (let index = 0; index < lineArr.value.length; index++) {
      if (index > 0) {
        const prev = lineArr.value[index - 1].time
        const next = lineArr.value[index].time
        if (prev <= time && next > time) {
          currentLyricLineId.value = lineArr.value[index - 1].id
          lineTextAnimation.value = `${next - prev}s`
          if (!stopScroll.value) {
            // 没有滑动时，才允许自动滚动
            linEl[index - 1].scrollIntoView({
              behavior: 'smooth', // 设置过渡动画：光滑
              block: 'center', // 设置垂直对齐：居中
            })
          }
        }
      }
    }
  }

  watch(
    () => store.state.currentPlaying,
    (newVal) => {
      if (newVal.id) {
        getSongLyric()
      }
    },
    {
      immediate: true,
    }
  )

  onMounted(() => {
    // 禁止鼠标滚动
    mainRef.value.addEventListener('mousewheel', (e: Event) => {
      e.preventDefault()
    })
  })

  return {
    lineArr,
    currentLyricLineId,
    lineTextAnimation,
    getLyricTime,
  }
}

const handleMainTouch = (stopScroll: Ref<boolean>) => {
  let timer: number | undefined = undefined
  const touchStartMain = () => {
    clearTimeout(timer)
    stopScroll.value = true
  }

  const touchEndMain = () => {
    timer = setTimeout(() => {
      stopScroll.value = false
    }, 1000)
  }

  return {
    touchStartMain,
    touchEndMain,
  }
}

export default defineComponent({
  name: 'Play',
  components: {
    SkyAudio,
  },
  setup() {
    const store = useStore()
    const playOrPause = computed(() => store.state.playOrPause)
    // 是否停止歌词跟随歌曲的滚动
    const stopScroll: Ref<boolean> = ref(false)
    // 滚动的div
    const mainRef: Ref<any> = ref(null)
    // 包含所有歌词的div
    const lineListRef: Ref<any> = ref(null)
    const { show, open, close } = handleVisible(store)

    const { songs, getSongDetail } = handleSongDetail(store)

    const { skyAuio, playAudio, pauseAudio } = handleAudio()

    const { lineArr, currentLyricLineId, lineTextAnimation, getLyricTime } =
      handleSongLyric(store, stopScroll, mainRef, lineListRef)

    const { touchStartMain, touchEndMain } = handleMainTouch(stopScroll)

    return {
      show,
      songs,
      skyAuio,
      lineArr,
      currentLyricLineId,
      lineListRef,
      lineTextAnimation,
      playOrPause,
      stopScroll,
      mainRef,
      open,
      close,
      getSongDetail,
      playAudio,
      pauseAudio,
      getLyricTime,
      touchStartMain,
      touchEndMain,
    }
  },
})
</script>

<style lang="less" scoped>
.play_page {
  position: fixed;
  left: 0;
  right: 0;
  height: 100vh;
  background: var(--sky-play-page-background-color);
  z-index: 5;
  &.show {
    top: 0;
  }
  &.hidden {
    top: 100vh;
  }
  .header {
    height: 50px;
    margin-bottom: 20px;
    .icon_box {
      width: 40px;
      .iconfont {
        font-size: 20px;
        color: var(--sky-text-white-color);
      }
    }
    .content {
      width: 0;
      .name {
        width: 100%;
        font-size: 16px;
        color: var(--sky-text-white-color);
        text-align: center;
      }
      .author {
        font-size: 14px;
        color: var(--sky-text-gray6-color);
        text-align: center;
      }
    }
  }

  .main {
    height: calc(100vh - 190px);
    overflow-x: hidden;
    overflow-y: auto;
    scroll-behavior: smooth;
    .line_list {
      padding: 0 16px;
      .list {
        padding-bottom: 15px;
        text-align: center;
        .text {
          font-size: 16px;
          background: var(--sky-text-gray6-color)
            var(--sky-redTored-background-color) no-repeat 0 0;
          line-height: 28px;
          -webkit-text-fill-color: transparent;
          background-clip: text;
          background-size: 0 100%;
        }
        &.active {
          .text {
            animation-name: scan;
            animation-timing-function: linear;
            animation-duration: 1s;
            animation-play-state: running;
          }
        }
      }
    }
  }

  .footer {
    height: 115px;
  }
}
</style>

<style>
.play_page_popup {
  height: 100vh;
}
</style>